//给你一个整数 n ，对于 0 <= i <= n 中的每个 i ，计算其二进制表示中 1 的个数 ，返回一个长度为 n + 1 的数组 ans 作为答案。 
//
//
// 
//
// 
// 
// 示例 1： 
//
// 
//输入：n = 2
//输出：[0,1,1]
//解释：
//0 --> 0
//1 --> 1
//2 --> 10
// 
//
// 示例 2： 
//
// 
//输入：n = 5
//输出：[0,1,1,2,1,2]
//解释：
//0 --> 0
//1 --> 1
//2 --> 10
//3 --> 11
//4 --> 100
//5 --> 101
// 
//
// 
//
// 提示： 
//
// 
// 0 <= n <= 10⁵ 
// 
//
// 
//
// 进阶： 
//
// 
// 很容易就能实现时间复杂度为 O(n log n) 的解决方案，你可以在线性时间复杂度 O(n) 内用一趟扫描解决此问题吗？ 
// 你能不使用任何内置函数解决此问题吗？（如，C++ 中的 __builtin_popcount ） 
// 
// 
// 
// Related Topics 位运算 动态规划 👍 1031 👎 0

package leetcode.editor.cn;

class CountingBits {
    public static void main(String[] args) {
        Solution solution = new CountingBits().new Solution();
        solution.countBits(9);
    }

    //leetcode submit region begin(Prohibit modification and deletion)
    class Solution {
        /*public int[] countBits(int n) {
            int[] array = new int[n + 1];
            array[0] = 0;
            for (int i = 1; i <= n; i++) {
                int count = 0;
                int temp = i;
                while (temp != 0) {
                    if ((temp & 1) == 1) count++;
                    temp >>= 1;
                }
                array[i] = count;
            }
            return array;
        }*/

        // Brian Kernighan 算法
        // 对于任意整数 x，令 x=x~\&~(x-1)x=x & (x−1)，
        // 该运算将 x 的二进制表示的最后一个 1 变成 0。因此，对 x 重复该操作，直到 x 变成 0，则操作次数即为 x 的「一比特数」。
        /*public int[] countBits(int n) {
            int[] bits = new int[n + 1];
            for (int i = 0; i <= n; i++) {
                bits[i] = countOnes(i);
            }

            return bits;
        }

        public int countOnes(int x) {
            int count = 0;
            while (x != 0) {
                x &= (x - 1);
                count++;
            }
            return count;
        }
*/
        // 动态规划——最高有效位
        /*public int[] countBits(int n) {
            int[] bits = new int[n + 1];
            int highBit = 0;   // 表示最高位
            for (int i = 1; i <= n; i++) {
                // 判断是否是2的幂
                if ((i & (i - 1)) == 0) {
                    highBit = i;
                }
                bits[i] = bits[i - highBit] + 1;
            }

            return bits;
        }*/

        // 动态规划——最低有效位
        /*public int[] countBits(int n) {
            int[] bits = new int[n + 1];
            for (int i = 0; i <= n; i++) {
                bits[i] = bits[i >> 1] + i % 2;
            }
            return bits;
        }*/

        // 方法四：动态规划——最低设置位
        public int[] countBits(int n) {
            int[] bits = new int[n + 1];
            for (int i = 1; i <= n; i++) {
                bits[i] = bits[i & (i - 1)] + 1;
            }
            return bits;
        }
    }
//leetcode submit region end(Prohibit modification and deletion)

}
